﻿using CDV.IRMS.WebAPI.TaskExecution.Data;
using CDV.IRMS.WebAPI.TaskExecution.Filter;
using CDV.IRMS.WebAPI.TaskExecution.Interface;
using CDV.IRMS.WebAPI.TaskExecution.Utils;
using log4net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace CDV.IRMS.WebAPI.TaskExecution.Controllers
{
    /// <summary>
    /// 任务路由执行API
    /// </summary>
    [Route("api/exec")]
    public class TaskExecutionController : Controller
    {
        #region Service
        //Log对象
        private readonly ILog _logger;

        /// <summary>
        /// 矩阵控制服务
        /// </summary>
        private readonly IMatrixControlService _matrixControlService;

        /// <summary>
        /// 任务管理服务
        /// </summary>
        private readonly ITaskManagerService _taskManagerService;

        /// <summary>
        /// 资源管理服务
        /// </summary>
        private readonly IResourceManagerService _resourceManagerService;

        /// <summary>
        /// 缓存服务
        /// </summary>
        private readonly ICacheService _cacheService;
        #endregion

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="serviceProvider">ServiceProvider</param>
        public TaskExecutionController(IServiceProvider serviceProvider)
        {
            _taskManagerService = serviceProvider.GetService<ITaskManagerService>();
            _matrixControlService = serviceProvider.GetService<IMatrixControlService>();
            _cacheService = serviceProvider.GetService<ICacheService>();
            _resourceManagerService = serviceProvider.GetService<IResourceManagerService>();
            _logger = serviceProvider.GetService<ILog>();
        }

        /// <summary>
        /// 获取任务路由列表
        /// </summary>
        /// <remarks>
        /// ■请求例:
        ///     /api/exec/list?beginTime={beginTime}&amp;endTime={endTime}&amp;routeStatus={routeStatus?}
        /// 
        /// ■返回值:
        /// {
        ///     RouteList：List&lt;TaskRouteInfoModel&gt;()
        ///     ErrorMsg：string
        /// }
        /// </remarks>
        /// <param name="beginTime">开始时间</param>
        /// <param name="endTime">结束时间</param>
        /// <param name="routeStatus">路由状态</param>
        /// <returns>任务路由列表</returns>
        [HttpGet("list")]
        [ValidateModel("获取任务路由列表")]
        public IActionResult List(DateTime beginTime, DateTime endTime, int? routeStatus)
        {
            var result = _taskManagerService.QueryTask(beginTime, endTime, routeStatus);
            return new JsonResult(new { RouteList = result.Item1, ErrorMsg = result.Item2 });
        }

        /// <summary>
        /// 路由执行
        /// </summary>
        /// <param name="parameter">执行参数</param>
        /// <remarks>
        /// ■返回值:
        /// {
        ///     TaskID：int
        ///     RouteID：int
        ///     ErrorMsg：string
        /// }
        /// </remarks>
        /// <returns>(任务ID,路由ID,错误信息)</returns>
        [HttpPost("execute")]
        [ValidateModel("任务路由执行")]
        public IActionResult Execute([FromBody]ExecuteParameter parameter)
        {
            //节点资源校验
            var checkResult = _resourceManagerService.HasNodeConflict(parameter.TaskID, parameter.RouteID, parameter.SrcNodeID, parameter.DestNodeID);
            if (checkResult.Item1)
            {
                return ActionResultGenerator.CreateJsonResult(parameter.TaskID, parameter.RouteID, checkResult.Item2);
            }

            return RouteExecute(parameter);
        }

        /// <summary>
        /// 路由应急切
        /// </summary>
        /// <param name="parameter">路由应急切参数</param>
        /// <remarks>
        /// ■返回值:
        /// {
        ///     TaskID：int
        ///     RouteID：int
        ///     ErrorMsg：string
        /// }
        /// </remarks>
        /// <returns>(任务ID,路由ID,错误信息)</returns>
        [HttpPost("take")]
        [ValidateModel("任务路由应急切")]
        public IActionResult ForceTake([FromBody]ExecuteParameter parameter)
        {
            return RouteExecute(parameter);
        }

        /// <summary>
        /// 结束路由执行
        /// </summary>
        /// <param name="taskID">任务ID</param>
        /// <param name="routeID">路由ID</param>
        /// <remarks>
        /// ■请求例:
        ///     /api/exec/finish/{taskID}/{routeID}
        /// 
        /// ■返回值:
        /// {
        ///     TaskID：int
        ///     RouteID：int
        ///     ErrorMsg：string
        /// }
        /// </remarks>
        /// <returns>(任务ID,路由ID,错误信息)</returns>
        [HttpPut("finish/{taskID}/{routeID}")]
        [ValidateModel("结束路由执行")]
        public IActionResult Finish(int taskID, int routeID)
        {
            //设置路由状态
            var updateResult = UpdateRouteLineStatus(taskID, routeID, ERouteStatus.Finish);
            if (!updateResult.Item1)
            {
                return ActionResultGenerator.CreateJsonResult(taskID, routeID, updateResult.Item2);
            }

            //如果该节点被锁定，则解除锁定
            var destNodeID = _cacheService.RemoveLockedNode(taskID, routeID);
            if (!string.IsNullOrEmpty(destNodeID))
            {
                var unlockResult = _matrixControlService.UnLock(destNodeID);
                if (!unlockResult.Item1)
                {
                    _logger.Error($"矩阵目的流端口解锁失败，原因-[{unlockResult.Item2}]");
                }
            }

            return ActionResultGenerator.CreateJsonResult(taskID, routeID);
        }

        /// <summary>
        /// 路由复位
        /// </summary>
        /// <param name="taskID">任务ID</param>
        /// <param name="routeID">路由ID</param>
        /// <remarks>
        /// ■请求例:
        ///     /api/exec/reset/{taskID}/{routeID}
        /// 
        /// ■返回值:
        /// {
        ///     TaskID：int
        ///     RouteID：int
        ///     ErrorMsg：string
        /// }
        /// </remarks>
        /// <returns>(任务ID,路由ID,错误信息)</returns>
        [HttpPut("reset/{taskID}/{routeID}")]
        [ValidateModel("任务路由复位")]
        public IActionResult Reset(int taskID, int routeID)
        {
            //设置路由状态
            var updateResult = UpdateRouteLineStatus(taskID, routeID, ERouteStatus.None);
            if (!updateResult.Item1)
            {
                return ActionResultGenerator.CreateJsonResult(taskID, routeID, updateResult.Item2);
            }

            return ActionResultGenerator.CreateJsonResult(taskID, routeID);
        }

        /// <summary>
        /// 更新任务路由的线路状态
        /// </summary>
        /// <param name="taskID">任务ID</param>
        /// <param name="routeID">路由ID</param>
        /// <param name="routeStatus">路由线路状态</param>
        /// <returns>(更新结果，错误信息)</returns>
        private (bool, string) UpdateRouteLineStatus(int taskID, int routeID, ERouteStatus routeStatus)
        {
            var updateResult = _taskManagerService.UpdateRouteStatus(taskID, routeID, routeStatus);
            if (updateResult.Item1)
            {
                return (true, string.Empty);
            }

            return (false, $"任务路由的执行状态[{routeStatus}({(int)routeStatus})]设置失败，原因-[{updateResult.Item2}]");
        }

        /// <summary>
        /// 路由执行
        /// </summary>
        /// <param name="parameter">路由执行参数</param>
        /// <returns>(任务ID,路由ID,错误信息)</returns>
        private IActionResult RouteExecute(ExecuteParameter parameter)
        {
            //设置路由状态
            var updateResult = UpdateRouteLineStatus(parameter.TaskID, parameter.RouteID, ERouteStatus.Executing);
            //路由状态设置失败
            if (!updateResult.Item1)
            {
                return ActionResultGenerator.CreateJsonResult(parameter.TaskID, parameter.RouteID, updateResult.Item2);
            }

            //不执行矩阵切换
            if (!parameter.DoTake)
            {
                _logger.Info($"任务路由执行未执行矩阵切换，入参-[{parameter}]");
                return ActionResultGenerator.CreateJsonResult(parameter.TaskID, parameter.RouteID);
            }

            //矩阵切换
            var takeResult = _matrixControlService.Take(parameter.SrcNodeID, parameter.DestNodeID);
            //矩阵切换失败
            if (!takeResult.Item1)
            {
                return ActionResultGenerator.CreateJsonResult(parameter.TaskID, parameter.RouteID, $"矩阵切换失败，原因-[{takeResult.Item2}]");
            }

            //不执行端口保护
            if (!parameter.DoLock)
            {
                _logger.Info($"任务路由执行未执行端口保护，入参-[{parameter}]");
                return ActionResultGenerator.CreateJsonResult(parameter.TaskID, parameter.RouteID);
            }

            //锁定端口
            var lockResult = _matrixControlService.Lock(parameter.DestNodeID);
            //端口锁定失败
            if (!lockResult.Item1)
            {
                _logger.Error($"矩阵目的流端口锁定失败，入参-[{parameter}]，原因-[{takeResult.Item2}]");
            }
            else
            {
                //缓存锁定节点ID
                _cacheService.AddLockedNode(parameter.TaskID, parameter.RouteID, parameter.DestNodeID);
            }

            return ActionResultGenerator.CreateJsonResult(parameter.TaskID, parameter.RouteID);
        }
    }
}
